<?php
/**
 * rTorrent Server Module
 *
 * Provides rTorrent server support uTorrent Bridge.
 *
 * @version		0.1.1
 * @package		bridge
 * @copyright	Copyright (c) 2009,
 * 				Ryon Sherman <ryon.sherman@gmail.com>
 * @license		http://www.gnu.org/licenses/gpl.txt The GNU Public License
 */

/**
 * rTorrent Build
 *
 * Last supported rTorrent Build.
 */
define('RTORRENT_BUILD', '0.8.4');

/**
 * rTorrent RPC Request Size Limit
 *
 * Size limitation of RPC request.
 *
 * @internal	Increase if you experience problems with large torrents.
 */
define('RTORRENT_REQUEST_LIMIT', 2048);

/**
 * rTorrent Server Module
 *
 * Provides rTorrent server support uTorrent Bridge.
 *
 * @author		ryon.sherman
 *
 * @package		bridge
 * @subpackage	server
 */
class utb_server_rtorrent implements utb_server_interface
{
	/**
	 * RPC
	 *
	 * Remote Procedure Call interface.
	 *
	 * @see		utb_rtorrent_rpc
	 *
	 * @access	private
	 *
	 * @var		object
	 */
	private $_rpc;

	/**
	 * Constructor
	 *
	 * Attaches RPC interface.
	 *
	 * @see		utb_rtorrent_rpc
	 *
	 * @author	ryon.sherman
	 * @access	public
	 *
	 * @param	string	$user		Username
	 * @param	string	$pass		Password
	 */
	public function __construct($user, $pass)
	{
		# Attach RPC interface.
		$this->_rpc = new utb_rtorrent_rpc($user, $pass);
	}

	/**
	 * Get Transfer Files Action Override
	 *
	 * Retrieves files for transfer(s). Performs rTorrent specific
	 * actions.
	 *
	 * @see		utb_file_rtorrent
	 *
	 * @author	ryon.sherman
	 * @access	public
	 *
	 * @param	array	$hashes		Array of transfer hashes
	 *
	 * @return	array				Array of utb_file_rtorrent objects
	 */
	public function get_files($hashes)
	{
		# Prepare array of files.
		$files = array();

		# Extract single 'hash' value from
		# array of hashes.
		$hash = $hashes[0];

		# Retrieve number of files in transfer.
		$file_count = $this->_rpc->call('d.get_size_files', array($hash));

		# Prepare array of calls.
		$params = array();

		# Retrieve details of each file.
		for ($i = 0; $i < $file_count; $i++)
		{
			# Add transfer specific methods to array of calls.
			$params[] = array('f.get_path', 			array($hash, $i));
			$params[] = array('f.get_size_chunks', 		array($hash, $i));
			$params[] = array('f.get_completed_chunks',	array($hash, $i));
			$params[] = array('f.get_priority', 		array($hash, $i));
		}

		# Perform multicall.
		$details = $this->_rpc->multicall($params);

		# Prepare cursor.
		$cursor = 0;

		# Format details of each file.
		for ($i = 0; $i < $file_count; $i++)
		{
			# Prepare array of file details.
			$file = array();

			# Assign file specific details.
			$file['hash'] 				= $hash;
			$file['name'] 				= $details[$cursor++];
			$file['size'] 				= $details[$cursor++];
			$file['size_downloaded'] 	= $details[$cursor++];
			$file['priority'] 			= $details[$cursor++];

			# Create new file container.
			$file = new utb_file_rtorrent($file);

			# Add serilized file to array of returned files
			# using the current array of details.
			$files[] = $file->serialize();
		}

		# Return hash and array of files.
		return array($hash, $files);
	}

	/**
	 * Get Transfer Properties Action Override
	 *
	 * Retrieves properties for transfer(s). Performs rTorrent specific
	 * actions.
	 *
	 * @see		utb_properties
	 *
	 * @author	ryon.sherman
	 * @access	public
	 *
	 * @param	array	$hashes		Array of transfer hashes
	 *
	 * @return	array				Array of utb_properties objects
	 */
	public function get_properties($hashes)
	{
		# Prepare array of properties.
		$properties = array();

		# Extract single 'hash' value from
		# array of hashes.
		$hash = $hashes[0];

		# Retrieve transfer tracker size.
		$tracker_size = $this->_rpc->call('d.get_tracker_size', array($hash));

		# Prepare array of calls.
		$params = array();

		# Add server specific methods to array of calls.
		$params[] = array('get_upload_rate', 		array($hash));
		$params[] = array('get_download_rate', 		array($hash));
		$params[] = array('dht_statistics',			array($hash));
		$params[] = array('get_max_uploads', 		array($hash));
		# Add transfer specific methods to array of calls.
		$params[] = array('d.get_peer_exchange',	array($hash));
		# Add tracker specific methods to array of calls.
		for ($i = 0; $i < $tracker_size; $i++)
		{
			$params[] = array('t.get_url', 			array($hash, $i));
		}

		# Perform multicall. Retrieve details.
		$details = $this->_rpc->multicall($params);

		# Prepare cursor.
		$cursor = 0;

		# Assign server specific properties to array
		# of property data.
		$properties['hash'] 			= $hash;
		$properties['rate_upload']		= $details[$cursor++];
		$properties['rate_download'] 	= $details[$cursor++];
		$properties['dht'] 				= $details[$cursor++]['active'];
		$properties['upload_slots'] 	= $details[$cursor++];
		# Assign transfer specific properties to array
		# of property data.
		$properties['pex'] 				= $details[$cursor++];
		# Assign tracker specific properties to array
		# of property data.
		$properties['trackers'] = array();
		for ($i = 0; $i < $tracker_size; $i++)
		{
			$properties['trackers'][] = $details[$cursor++];
		}

		# Create new property container using
		# current array of property data.
		$properties = new utb_properties($properties);
		# Serialize property data.
		$properties = $properties->serialize();

		# Return transfer properties.
		return $properties;
	}

	/**
	 * Get Server Settings Action Override
	 *
	 * Retrieves server settings. Performs rTorrent specific
	 * actions.
	 *
	 * @todo	Support server setting retrieval.
	 *
	 * @author	ryon.sherman
	 * @access	public
	 *
	 * @return	array				Array of server settings and values
	 */
	public function get_settings()
	{
		# Return array placeholder.
		return array();
	}

	/**
	 * Get Transfers Action Override
	 *
	 * Retrieves transfers. Performs rTorrent specific
	 * actions.
	 *
	 * @see		utb_transfer_rtorrent
	 *
	 * @access	public
	 * @author	ryon.sherman
	 *
	 * @param	array	$views		Array of views
	 *
	 * @return	array				Array of utb_transfer_rtorrent objects
	 */
	public function get_transfers($views = array('main'))
	{
		# Prepare array of transfers.
		$transfers = array();

		# Retrieve array of hashes.
		$hashes = $this->_rpc->call('download_list', $views);

		# Prepare array of calls.
		$params = array();

		# Retrieve the tracker size of each transfer.
		foreach ($hashes as $hash)
		{
			$params[] = array('d.get_tracker_size', array($hash));
		}
		$tracker_sizes = $this->_rpc->multicall($params);

		# Clear previous array of calls.
		$params = array();

		# Retrieve details of each transfer.
		foreach ($hashes as $index => $hash)
		{
			# Add transfer specific methods to array of calls.
			$params[] = array('d.is_active', 			array($hash));
			$params[] = array('d.get_name', 			array($hash));
			$params[] = array('d.get_size_bytes', 		array($hash));
			$params[] = array('d.get_completed_chunks',	array($hash));
			$params[] = array('d.get_size_chunks', 		array($hash));
			$params[] = array('d.get_completed_bytes', 	array($hash));
			$params[] = array('d.get_up_total',			array($hash));
			$params[] = array('d.get_ratio', 			array($hash));
			$params[] = array('d.get_up_rate', 			array($hash));
			$params[] = array('d.get_down_rate', 		array($hash));
			$params[] = array('d.get_peers_accounted', 	array($hash));
			$params[] = array('d.get_peers_complete', 	array($hash));
			$params[] = array('d.get_left_bytes', 		array($hash));

			# Add tracker specific methods to array of calls.
			for ($i = 0; $i < $tracker_sizes[$index]; $i++)
			{
				$params[] = array('t.get_scrape_incomplete', array($hash, $i));
				$params[] = array('t.get_scrape_complete', array($hash, $i));
			}
		}

		# Perform multicall.
		$details = $this->_rpc->multicall($params);

		# Prepare cursor.
		$cursor = 0;

		# Format details of each transfer.
		foreach ($hashes as $index => $hash)
		{
			# Prepare array of transfer details.
			$transfer = array();

			# Assign transfer specific details.
			$transfer['hash'] 				= $hash;
			$transfer['status'] 			= $details[$cursor++];
			$transfer['name'] 				= $details[$cursor++];
			$transfer['size'] 				= $details[$cursor++];
			$transfer['total_chunks']		= $details[$cursor++];
			$transfer['completed_chunks'] 	= $details[$cursor++];
			$transfer['downloaded'] 		= $details[$cursor++];
			$transfer['uploaded'] 			= $details[$cursor++];
			$transfer['ratio'] 				= $details[$cursor++];
			$transfer['upload_speed'] 		= $details[$cursor++];
			$transfer['download_speed'] 	= $details[$cursor++];
			$transfer['peers_connected']	= $details[$cursor++];
			$transfer['seeds_connected'] 	= $details[$cursor++];
			$transfer['remaining'] 			= $details[$cursor++];

			# Assign tracker specific details.
			for ($i = 0; $i < $tracker_sizes[$index]; $i++)
			{
				$transfer['scrape_incomplete'][] = $details[$cursor++];
				$transfer['scrape_complete'][] = $details[$cursor++];
			}

			# Add new transfer to array of returned transfers
			# using the current array of details.
			$transfers[$hash] = new utb_transfer_rtorrent($transfer);
		}

		# Return array of transfers.
		return $transfers;
	}

	/**
	 * Set File Priority Action Override.
	 *
	 * Sets the priority of file(s). Performs rTorrent specific
	 * actions.
	 *
	 * @todo	Support transfer file priority assignment.
	 *
	 * @access	public
	 *
	 * @param	string	$hash		Transfer hash
	 * @param	integer	$file		File to modify
	 * @param	integer	$priority	Modified file priority
	 */
	public function set_priority($hash, $file, $priority)
	{
		//
	}

	/**
	 * Set Transfer Property Action Override
	 *
	 * Sets the properties of transfer(s). Performs rTorrent specific
	 * actions.
	 *
	 * @todo	Support transfer property assignment.
	 *
	 * @access	public
	 *
	 * @param	string	$hash		Transfer hash
	 * @param	string	$property	Property to modify
	 * @param	string	$value		Modified property value
	 */
	public function set_property($hash, $property, $value)
	{
		//
	}

	/**
	 * Set Server Setting Action Override
	 *
	 * Sets server setting(s). Performs rTorrent specific
	 * actions.
	 *
	 * @todo	Support server setting assignment.
	 *
	 * @access	public
	 *
	 * @param	string	$setting	Setting to modify
	 * @param	string	$value		Modified setting value
	 */
	public function set_setting($setting, $value)
	{
		//
	}

	/**
	 * Add Torrent File Action
	 *
	 * Adds a torrent via HTTP POST. Performs rTorrent specific
	 * actions.
	 *
	 * @todo	Support torrent addition via HTTP POST.
	 *
	 * @access	public
	 */
	public function add_file()
	{
		//
	}

	/**
	 * Add Torrent URL Action Override
	 *
	 * Adds a torrent via URL. Performs rTorrent specific
	 * actions.
	 *
	 * @access	public
	 * @author	ryon.sherman
	 *
	 * @param	string	$url		URL to add
	 */
	public function add_url($url)
	{
		# Perform 'load' server action.
		$this->_rpc->call('load', array($url));
	}

	/**
	 * Force Start Transfer(s) Action Override
	 *
	 * Force-Starts transfer(s). Performs rTorrent specific
	 * actions.
	 *
	 * @access	public
	 * @author	ryon.sherman
	 *
	 * @param	array	$hashes		Array of transfer hashes
	 */
	public function force_start($hashes)
	{
		# Perform 'start' server action.
		$this->start($hashes);
	}

	/**
	 * Pause Transfer(s) Action Override
	 *
	 * Pauses transfer(s). Performs rTorrent specific
	 * actions.
	 *
	 * @access	public
	 * @author	ryon.sherman
	 *
	 * @param	array	$hashes		Array of transfer hashes
	 */
	public function pause($hashes)
	{
		# Perform 'stop' server action.
		$this->stop($hashes);
	}

	/**
	 * Recheck Transfer Hash(es) Action Override
	 *
	 * Rechecks the hash of transfer(s). Performs rTorrent specific
	 * actions.
	 *
	 * @access	public
	 *
	 * @param	array	$hashes		Array of transfer hashes
	 */
	public function recheck($hashes)
	{
		# Prepare array of calls.
		$params = array();

		# Perform action on each transfer.
		foreach ($hashes as $hash)
		{
			# Add transfer specific methods to array of calls.
			$params[] = array('d.check_hash', array($hash));
		}

		# Perform 'd.check_hash' server actions.
		$this->_rpc->multicall($params);
	}

	/**
	 * Remove Transfer(s) Action
	 *
	 * Removes transfer(s).
	 *
	 * @access	public
	 *
	 * @param	array	$hashes		Array of transfer hashes
	 */
	public function remove($hashes)
	{
		# Prepare array of calls.
		$params = array();

		# Perform action on each transfer.
		foreach ($hashes as $hash)
		{
			# Add transfer specific methods to array of calls.
			$params[] = array('d.erase', array($hash));
		}

		# Perform 'd.erase' server actions.
		$this->_rpc->multicall($params);
	}

	/**
	 * Remove Transfer(s) With Data Action
	 *
	 * Removes transfer(s) and delete files.
	 *
	 * @access	public
	 *
	 * @param	array	$hashes		Array of transfer hashes
	 */
	public function remove_data($hashes)
	{
		# Perform 'remove' server action.
		$this->remove($hashes);
	}

	/**
	 * Restart Transfer(s) Action
	 *
	 * Restarts transfer(s).
	 *
	 * @access	public
	 *
	 * @param	array	$hashes		Array of transfer hashes
	 */
	public function restart($hashes)
	{
		# Prepare array of calls.
		$params = array();

		# Perform action on each transfer.
		foreach ($hashes as $hash)
		{
			# Add transfer specific methods to array of calls.
			$params[] = array('d.stop', array($hash));
			$params[] = array('d.start', array($hash));
		}

		# Perform 'd.stop' and 'd.start' server actions.
		$this->_rpc->multicall($params);
	}

	/**
	 * Start Transfer(s) Action
	 *
	 * Starts transfer(s).
	 *
	 * @access	public
	 *
	 * @param	array	$hashes		Array of transfer hashes
	 */
	public function start($hashes)
	{
		# Prepare array of calls.
		$params = array();

		# Perform action on each transfer.
		foreach ($hashes as $hash)
		{
			# Add transfer specific methods to array of calls.
			$params[] = array('d.start', array($hash));
		}

		# Perform 'd.start' server actions.
		$this->_rpc->multicall($params);
	}

	/**
	 * Stop Transfer(s) Action
	 *
	 * Stops transfer(s).
	 *
	 * @access	public
	 *
	 * @param	array	$hashes		Array of transfer hashes
	 */
	public function stop($hashes)
	{
		# Prepare array of calls.
		$params = array();

		# Perform action on each transfer.
		foreach ($hashes as $hash)
		{
			# Add transfer specific methods to array of calls.
			$params[] = array('d.stop', array($hash));
		}

		# Perform 'd.stop' server actions.
		$this->_rpc->multicall($params);
	}

	/**
	 * Unpause Transfer(s) Action
	 *
	 * Un-Pauses transfer(s).
	 *
	 * @access	public
	 *
	 * @param	array	$hashes		Array of transfer hashes
	 */
	public function unpause($hashes)
	{
		# Perform 'start' server action.
		$this->start($hashes);
	}
}

/**
 * rTorrent RPC Interface
 *
 * Contains methods for accessing the XMLRPC
 * interface used by rTorrent.
 *
 * @author		ryon.sherman
 *
 * @package		bridge
 * @subpackage	server.rtorrent
 *
 * @todo		Support 64 bit integers
 */
class utb_rtorrent_rpc
{
	/**
	 * Username
	 *
	 * Username used for authenticating with the
	 * RPC interface.
	 *
	 * @access	private
	 *
	 * @var		string
	 */
	private $_user;

	/**
	 * Password
	 *
	 * Password used for authenticating with the
	 * RPC interface.
	 *
	 * @access	private
	 *
	 * @var		string
	 */
	private $_pass;

	/**
	 * Constructor
	 *
	 * Assigns RPC interface authentication values.
	 *
	 * @access	public
	 * @author	ryon.sherman
	 *
	 * @param	string	$user		Interface username
	 * @param	string	$pass		Interface password
	 */
	public function __construct($user, $pass)
	{
		# Assign interface username class value.
		$this->_user = $user;

		# Assign interface password class value.
		$this->_pass = $pass;

		# Set RPC request size limit.
		$this->_set_request_limit();
	}

	/**
	 * Set Request Limit
	 *
	 * Sets the RPC request limit on an rTorrent server.
	 *
	 * @access	public
	 * @author	ryon.sherman
	 */
	private function _set_request_limit()
	{
		# Calculate and assign request limit size.
		$limit = RTORRENT_REQUEST_LIMIT * 1000;

		# Perform 'set_xmlrpc_size_limit' server action.
		$this->call('set_xmlrpc_size_limit', array($limit));
	}

	/**
	 * Call
	 *
	 * Performs a single RPC call.
	 *
	 * @access	public
	 * @author	ryon.sherman
	 *
	 * @param	string	$method					Method to perform
	 * @param	array	$params					Array of parameters
	 *
	 * @return	array|integer|string|boolean	Call result
	 */
	public function call($method, $params = array())
	{
		# Base64 encode username:password.
		$auth = base64_encode("{$this->_user}:{$this->_pass}");

		# Encode XMLRPC request.
		$request = xmlrpc_encode_request($method, $params);

		# Build custom stream context.
		$context = stream_context_create(array('http' => array(
			'method' 	=> "POST",
			'header' 	=> "Content-Type: text/xml\r\n".
							"Authorization: Basic {$auth}",
			'content'	=> $request,
		)));

		# Retreive XML file.
		$file = file_get_contents(SERVER_URL, false, $context);

		# TODO: Implement: Support 64 bit integers. This workaround will do for now.
		$file = str_replace('i8>', 'i4>', $file);

		# Decode XML.
		$response = xmlrpc_decode($file);
		# Check if XML contains errors.
		if ( @ xmlrpc_is_fault($response))
		{
			# Trigger PHP error, caught by custom error handler.
			trigger_error('xmlrpc: '.$response['faultString'].' ('.$response['faultCode'].')', E_USER_WARNING);
		}
		else
		{
			# Return result.
			return $response;
		}
	}

	/**
	 * Multicall
	 *
	 * Performs multiple RPC calls in a single HTTP request.
	 *
	 * @access	public
	 * @author	ryon.sherman
	 *
	 * @param	array	$params		Array of parameters
	 * @return	array				Array of results
	 */
	public function multicall($params = array())
	{
		# Build array of calls.
		$temp = array();
		foreach ($params as $param)
		{
			$temp[] = array(
				'methodName' 	=> $param[0],
				'params' 		=> $param[1],
			);
		}
		$params = array($temp);
		unset($temp);

		# Perform a single request of multiple calls.
		$responses = $this->call('system.multicall', $params);

		# Format array of results.
		foreach ($responses as $index => $response)
		{
			$responses[$index] = $response[0];
		}

		# Return results.
		return $responses;
	}
}

/**
 * rTorrent Transfer Container
 *
 * Contains overridden methods for utilizing a single
 * rTorrent transfer.
 *
 * @package		bridge
 * @subpackage	transfer
 * @author		ryon.sherman
 */
class utb_transfer_rtorrent extends utb_transfer
{
	/**
	 * rTorrent Transfer Class Constructor
	 *
	 * Parses transfer data and assigns class values.
	 *
	 * @author	ryon.sherman
	 * @access	public
	 *
	 * @param	array	$data		Array of transfer data
	 */
	public function __construct($data)
	{
		# Perform parent class construction.
		parent::__construct($data);
	}

	/**
	 * Set Transfer Status Override
	 *
	 * Parses array of transfer data and assigns the
	 * 'status' class value. Performs rTorrent specific
	 * calculations.
	 *
	 * @todo	Improve status result
	 *
	 * @author	ryon.sherman
	 * @access	public
	 *
	 * @param	array	$data		Array of transfer data
	 */
	public function set_status($data)
	{
		# TODO: Refactor: Improve status result.
		# rTorrent uses 'Active' and 'Non Active' statuses,
		# using status 201 for active and 136 for inactive
		# until statuses are refined.

		# Check if array of transfer data contains a valid
		# 'status' value.
		if ( ! empty($data['status']))
		{
			# Determine if 'status' is populated and
			# assign class value from array of transfer data.
			$this->status = ($data['status']) ? 201 : 136;
		}
	}

	/**
	 * Set Transfer Progress Override
	 *
	 * Parses array of transfer data and assigns the
	 * 'progress' class value. Performs rTorrent specific
	 * calculations.
	 *
	 * @author	ryon.sherman
	 * @access	public
	 *
	 * @param	array	$data		Array of transfer data
	 */
	public function set_progress($data)
	{
		# Check if array of transfer data contains valid
		# 'total_chunks' and 'completed_chunks' values.
		if ( ! empty($data['total_chunks']) and ! empty($data['completed_chunks']))
		{
			# Assign 'total_chunks' value
			# from array of transfer data.
			$total_chunks = $data['total_chunks'];
			# Assign 'completed_chunks' value
			# from array of transfer data.
			$completed_chunks = $data['completed_chunks'];

			# Check if 'total_chunks' is not default.
			if ($total_chunks > 0)
			{
				# Calculate and assign 'progress' class value.
				$this->progress = floor(($completed_chunks / $total_chunks) * 1000);
			}
		}
	}

	/**
	 * Set Transfer ETA Override
	 *
	 * Parses array of transfer data and assigns the
	 * 'eta' class value. Performs rTorrent specific
	 * calculations.
	 *
	 * @author	ryon.sherman
	 * @access	public
	 *
	 * @param	array	$data		Array of transfer data
	 */
	public function set_eta($data)
	{
		# Check if transfer is downloading and not complete.
		if ($this->progress == 1000 or $this->rate_download <= 0)
		{
			# Return 0 since ETA is infinite.
			return 0;
		}

		# Check if transfer is complete.
		if ($this->remaining <= 0)
		{
			# Return ETA of 0.
			return 0;
		}

		# Calculate and assign 'eta' class value.
		$this->eta = $this->remaining / $this->rate_download;
	}

	/**
	 * Set Total Transfer Peers Override
	 *
	 * Parses array of transfer data and assigns the
	 * 'peers_total' class value. Performs rTorrent specific
	 * calculations.
	 *
	 * @author	ryon.sherman
	 * @access	public
	 *
	 * @param	array	$data		Array of transfer data
	 */
	public function set_peers_total($data)
	{
		# Check if array of transfer data contains a valid
		# 'scrape_incomplete' value.
		if ( ! empty($data['scrape_incomplete']))
		{
			# Calculate peers from each tracker scrape.
			$peers = 0;
			foreach ($data['scrape_incomplete'] as $scrape)
			{
				$peers += $scrape;
			}

			# Assign 'peers_total' class value from
			# calculated total.
			$this->peers_total = $peers;
		}
	}

	/**
	 * Set Total Transfer Seeds Override
	 *
	 * Parses array of transfer data and assigns the
	 * 'seeds_total' class value. Performs rTorrent specific
	 * calculations.
	 *
	 * @author	ryon.sherman
	 * @access	public
	 *
	 * @param	array	$data		Array of transfer data
	 */
	public function set_seeds_total($data)
	{
		# Check if array of transfer data contains a valid
		# 'scrape_complete' value.
		if ( ! empty($data['scrape_complete']))
		{
			# Calculate seeds from each tracker scrape.
			$seeds = 0;
			foreach ($data['scrape_complete'] as $scrape)
			{
				$seeds += $scrape;
			}

			# Assign 'seeds_total' class value from
			# calculated total.
			$this->seeds_total = $seeds;
		}
	}

	/**
	 * Set Transfer Availability Override
	 *
	 * Parses array of transfer data and assigns the
	 * 'availability' class value. Performs rTorrent specific
	 * calculations.
	 *
	 * @author	ryon.sherman
	 * @access	public
	 *
	 * @param	array	$data		Array of transfer data
	 */
	public function set_availability($data)
	{
		# Check if transfer contains seeds.
		if ($this->seeds_total <= 0)
		{
			# Return 0 since transfer contains
			# no seeds.
			return 0;
		}

		# Calculate and assign 'availabilty' class value.
		$this->availability = floor(($this->seeds_total / $this->peers_total) * 65536);
	}
}

/**
 * rTorrent File Container
 *
 * Contains overridden methods for utilizing a single
 * transfer file.
 *
 * @package		bridge
 * @subpackage	file
 * @author		ryon.sherman
 */
class utb_file_rtorrent extends utb_file
{
	/**
	 * rTorrent File Class Constructor
	 *
	 * Parses file data and assigns class values.
	 *
	 * @author	ryon.sherman
	 * @access	public
	 *
	 * @param	array	$data		Array of file data
	 */
	public function __construct($data)
	{
		# Perform parent class construction.
		parent::__construct($data);
	}

	/**
	 * Set Total File Size Override
	 *
	 * Parses array of file data and assigns the
	 * 'size' class value. Performs rTorrent specific
	 * calculations.
	 *
	 * @author	ryon.sherman
	 * @access	public
	 *
	 * @param	array	$data		Array of file data
	 */
	public function set_size($data)
	{
		# Check if array of file data contains a valid
		# 'size' value.
		if ( ! empty($data['size']))
		{
			# Calculate and assign 'size' class value from array
			# of file data.
			$this->size = $data['size'] * 1000000;
		}
	}

	/**
	 * Set Downloaded File Size Override
	 *
	 * Parses array of file data and assigns the
	 * 'size_downloaded' class value. Performs rTorrent specific
	 * calculations.
	 *
	 * @author	ryon.sherman
	 * @access	public
	 *
	 * @param	array	$data	Array of file data
	 */
	public function set_size_downloaded($data)
	{
		# Check if array of file data contains a valid
		# 'size_downloaded' value.
		if ( ! empty($data['size_downloaded']))
		{
			# Calculate and assign 'size_downloaded' class value from array
			# of file data.
			$this->size_downloaded = $data['size_downloaded'] * 1000000;
		}
	}
}
?>